package com.tutu.utils;

import com.tutu.core.Constant;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.logging.Logger;

/**
 * 公众接口http请求发起通用工具类
 */
@Slf4j
public class HttpRequestUtil {

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();

        try {
            param = param.replace("null", "");

            URL realUrl = new URL(url);

            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();

            // 设置通用的请求属性
            conn.setRequestProperty("token", Constant.DEFAULT_TOKEN);
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

            // 设置超时时间，单位：毫秒
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);

            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);

            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());

            // 发送请求参数
            out.print(param);

            // flush输出流的缓冲
            out.flush();

            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));

            String line;
            while ((line = in.readLine()) != null) result.append(line);
        } catch (Exception e) {
            log.info("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        } finally {
            //使用finally块来关闭输出流、输入流
            try {
                if (null != out) out.close();

                if (null != in) in.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        return result + "";
    }

    /**
     * 根据请求路径及请求参数获取对应的列表信息
     *
     * @param url    请求路径
     * @param params 请求参数
     * @return 列表信息
     */
    public static JSONArray getListData(String url, String params, String... passObj) {
        Map<String, Object> map;
        JSONArray jsonArray;

        String info = HttpRequestUtil.sendPost(ConfigUtil.getString("server.url") + url, checkStr(params));

        if (BaseUtil.isNotBlank(info)) {
            map = JsonUtil.json2Map(info, passObj);

            if (map.get("code").equals(0)) {
                if (BaseUtil.isBlank(map.get("data") + "")) return new JSONArray();

                jsonArray = JSONArray.fromObject(map.get("data"));

                if (jsonArray.size() > 0) return jsonArray;
            } else {
                Logger.getGlobal().info(map.get("msg") + " 服务器访问失败 ==> " + url + " 参数：" + params);
            }
        }

        return new JSONArray();
    }

    /**
     * 根据请求路径及请求参数获取对应的完整信息
     */
    public static Map<String, Object> getSyncData(Integer type) {
        String info = HttpRequestUtil.sendPost(ConfigUtil.getString("server.url") + "init", checkStr("type=" + type));

        if (BaseUtil.isNotBlank(info)) return JsonUtil.json2Map(info);

        return BaseUtil.defaultErrorInfo(null);
    }

    /**
     * 根据请求路径及请求参数获取对应的完整信息
     *
     * @param url    请求路径
     * @param params 请求参数
     * @return 完整信息
     */
    public static Map<String, Object> getCompleteData(String url, String params, String... passObj) {
        String info = HttpRequestUtil.sendPost(ConfigUtil.getString("server.url") + url, checkStr(params));

        if (BaseUtil.isNotBlank(info)) return JsonUtil.json2Map(info, passObj);

        return BaseUtil.defaultErrorInfo(null);
    }

    /**
     * 根据请求路径及请求参数获取对应的完整信息
     *
     * @param url    请求路径
     * @param params 请求参数
     * @return 完整信息
     */
    public static Map<String, Object> getNoModuleCompleteData(String url, String params, String... passObj) {
        String info = HttpRequestUtil.sendPost(ConfigUtil.getString("server.url").replace("/module", "") + url, checkStr(params));

        if (BaseUtil.isNotBlank(info)) return JsonUtil.json2Map(info, passObj);

        return BaseUtil.defaultErrorInfo(null);
    }

    /**
     * 根据请求路径及请求参数获取对应的data信息
     *
     * @param url    请求路径
     * @param params 请求参数
     * @return data信息
     */
    public static Map<String, Object> getOnlyData(String url, String params, String... passObj) {
        Map<String, Object> map;
        String info = HttpRequestUtil.sendPost(ConfigUtil.getString("server.url") + url, checkStr(params));

        if (BaseUtil.isNotBlank(info)) {
            map = JsonUtil.json2Map(info, passObj);

            if (map.get("code").equals(0)) {
                return JsonUtil.json2Map(map.get("data"), passObj);
            } else {
                return url.contains("/page") ? BaseUtil.defaultPageErrorInfo() : BaseUtil.defaultErrorInfo(map.get("msg") + "");
            }
        }

        return url.contains("/page") ? BaseUtil.defaultPageErrorInfo() : BaseUtil.defaultErrorInfo(null);
    }

    /**
     * 过滤掉空值
     *
     * @param content 需要过滤的字符串
     * @return 过滤完成的字符串
     */
    public static String checkStr(String content) {
        if (BaseUtil.isBlank(content)) return content;

        String[] val = content.split("&");
        String[] temp;
        StringBuilder result = new StringBuilder();

        for (String s : val) {
            temp = s.split("=");

            if (temp.length != 2) continue;

            if (temp[0].equals("id")) {
                result.append(s).append("&");
            } else {
                if (BaseUtil.isNotBlank(temp[1]) && !temp[1].equals("null")) result.append(s).append("&");
            }
        }

        return result.length() > 0 ? result.substring(0, result.length() - 1) : result + "";
    }
}